﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

using Sonic.Framework.Interfaces;
using Sonic.Framework.Enums;
using System.Xml;
using System.Text.RegularExpressions;

namespace Sonic.Framework.ProcessorToolDirectives.Default
{
    /// <summary>
    /// Filters out files from the processor tool file list
    /// </summary>
    public class ExcludeFilter : IPluginBase, IProcessorToolDirective
    {
        private const string _name = "ExcludeFilter";
        public string Name
        {
            get { return _name; }
        }

        private Dictionary<string, string> _attributes;
        public Dictionary<string, string> Attributes
        {
            get
            {
                return _attributes;
            }
        }

        public ExcludeFilter()
        {
            this._attributes = new Dictionary<string, string>();
        }

        public bool Execute(ISonicProcessor processor, ISiteDirectory siteDir, ref List<FileInfo> directoryFileInfos, XmlDocument argumentsXml)
        {
            List<FileInfo> filesToExclude = new List<FileInfo>();

            // Load details about paths to concatenate
            XmlNodeList paths = argumentsXml.SelectNodes("/Arguments/Directive/Path");
            foreach (XmlNode path in paths)
            {
                ExclusionType exclusionType = ExclusionType.ProcessorTool;
                switch (path.Attributes["type"].Value)
                {
                    case "ProcessorToolDirective":
                        exclusionType = ExclusionType.ProcessorToolDirective;
                        break;
                    case "ProcessorTool":
                        exclusionType = ExclusionType.ProcessorTool;
                        break;
                }

                bool deleteMatchingFiles = false;
                try
                {
                    deleteMatchingFiles = bool.Parse(GetDirectiveCallAttributeFromArgXml(argumentsXml, "deleteMatchingFiles"));
                }
                catch { }

                string processorToolDirectiveName = null;
                if (path.Attributes["name"] != null)
                {
                    processorToolDirectiveName = path.Attributes["name"].Value;
                }

                SitePathScope scope = SitePathScope.File;
                if (path.Attributes["scope"] != null)
                {
                    scope = (SitePathScope)Enum.Parse(typeof(SitePathScope), path.Attributes["scope"].Value);
                }

                string relativeFilePath = path.InnerText;

                if (scope == SitePathScope.File)
                {
                    FileInfo file = new FileInfo(RelativizePath(siteDir.DirectoryInfo.FullName, relativeFilePath));

                    if (deleteMatchingFiles)
                    {
                        directoryFileInfos.Remove(file);
                        file.Delete();
                    }
                    else
                    {
                        switch (exclusionType)
                        {
                            case ExclusionType.ProcessorToolDirective:
                                siteDir.Exclude(file, exclusionType, processorToolDirectiveName);
                                break;
                            case ExclusionType.ProcessorTool:
                                siteDir.Exclude(file, exclusionType);
                                break;
                        }
                    }

                } else if (scope == SitePathScope.Directory)
                {
                    DirectoryInfo dir = new DirectoryInfo(RelativizePath(siteDir.DirectoryInfo.FullName, relativeFilePath));

                    switch (exclusionType)
                    {
                        case ExclusionType.ProcessorToolDirective:
                            siteDir.Exclude(dir, exclusionType, processorToolDirectiveName);
                            break;
                        case ExclusionType.ProcessorTool:
                            siteDir.Exclude(dir, exclusionType);
                            break;
                    }
                }
                
            }

            return true;
        }

    }
}
